Home
Posted By: Pendragon Bookmark shortcuts problem in Safari 8.0 - 11/24/14 12:24 PM
Upon launching Safari 8.0, the bookmark shortcuts ⌘1, ⌘2, etc, do not work until I first click on one of the shortcuts in the Menu Bar. From then on the keyboard shortcuts work as divined. Well, until I quit Safari, then I must repeat the procedure.

This does not happen on my wife’s machine, so I fear ’tis moi or perhaps a bug unique to my machine.

FWIW, I am using an Apple wired keyboard.

Musings welcome.
I've begun turning off my extensions as the first troubleshooting step in the instance of any Safari glitch.
Originally Posted By: artie505
I've begun turning off my extensions as the first troubleshooting step in the instance of any Safari glitch.


Many thanks for the suggestion. I had not tried that, so the idea was most welcome. But alas, no joy.

I have hunted around in Cocktail, MacPilot, & TinkerTool System thinking there may have been a setting I inadvertently enabled, but that too proved fruitless.
Have you tried turning Rapport off, or is your wife running it too, making the question moot?
Originally Posted By: artie505
Have you tried turning Rapport off, or is your wife running it too, making the question moot?


No Rapport on my wife's machine, so I eagerly gave your suggestion a go. But it was no go. confused

AFAIK, shortcuts in all other apps work as designed.
Sorry to make such a mundane suggestion, but have you tried moving ~/Library/Preferences/com.apple.Safari.plist to your desktop, etc...? shocked
Originally Posted By: artie505
Sorry to make such a mundane suggestion, but have you tried moving ~/Library/Preferences/com.apple.Safari.plist to your desktop, etc...? shocked


As a matter of fact, I had not tried that, so 'twas well worth the effort. That I did not achieve success is still worthy. At least that is one more possibility that can now be ruled out.

Originally Posted By: artie505
Sorry to make such a mundane suggestion, but have you tried moving ~/Library/Preferences/com.apple.Safari.plist to your desktop, etc...? shocked

The defaults system has gotten very aggressive about caching. The phrases "move ~/Library/Preferences/whatever.plist to ..." and "delete/trash ~/Library/Preferences/whatever.plist" should set off alarms. They do not (reliably) do what you think they do, even though they used to (sort of).

The "defaults system" is embodied in a background process named cfprefsd (short for Core Foundation PREFerenceS Daemon"). Initially, right after login, cfprefsd knows nothing. As applications start up, they ask cfprefsd for their saved settings. The first time each application asks, cfprefsd reads and memorizes the corresponding .plist file. If an application changes a setting, it tells cfprefsd, which adjusts its memory of the application's settings. By and by, cfprefsd will write its amended knowledge to the .plist file, completely overwriting the previous file if it's still there.

The point is, cfprefsd tries to read the .plist file only once. Once it has read the file, nothing you do to the file has any effect on that application's defaults. (It used to be that when the application quit, cfprefsd would write out any changes and then forget the file. Relaunching the application would cause it to again ask cfprefsd for its settings, at which time cfprefsd would try re-reading the file. That opened up a window for you; deleting/moving the .plist file while the application was not running was an event that cfprefsd would notice. cfprefsd no longer forgets so quickly.)

The proper way to "forget" an application's saved preferences is to tell cfprefsd to delete them. cfprefsd will eventually propagate that deletion back to the .plist file, either by deleting it or rewriting it as an essentially empty file, but that's an implementation detail. The important point is that you should not be manipulating the .plist file yourself. Let cfprefsd manipulate the file.

Your interface to cfprefsd is through the defaults command in Terminal.

If you suspect an application's preferences have somehow gotten garbled, and want to set them back to their initial settings:
  • Quit the application. (Once an application has gotten a value from cfprefsd, it may itself cache the value, and nothing you tell cfprefsd will budge the application's memory of The Way Things Areâ„¢.)
  • Optionally, move the .plist file elsewhere. (You're only doing this so you can later restore these settings. This move does not affect cfprefsd.)
  • In Terminal, enter the command:
    defaults delete application.bundle.id
  • Re-launch the application.
If you've saved a previous .plist file and want to restore it:
  • Quit the application. (Same reason as before.)
  • In Terminal, enter the command:
    defaults write application.bundle.id "$(defaults read path/to/saved.plist)"
    This copies the saved file into cfprefsd's memory, making it available to the app and eventually causing the .plist file to be re-written.
  • Re-launch the app.


Each application has a "bundle id", which is how it identifies itself to cfprefsd when it asks for "its" saved settings, and is therefore how you must identify the app in the defaults command. Sometimes the bundle id is obvious (for example, Safari's is com.apple.Safari), but sometimes less so (for example, Calendar's is com.apple.iCal). You can learn an application's bundle id by entering the Terminal command
osascript -e 'id of application "application name" '

For example, try
osascript -e 'id of application "Contacts" '

Alternatively, the application's preferences are stored in ~/Library/Preferences/application.bundle.id.plist, so if you've found that file you can just pull the application.bundle.id from the filename.
Originally Posted By: ganbustein
Originally Posted By: artie505
Sorry to make such a mundane suggestion, but have you tried moving ~/Library/Preferences/com.apple.Safari.plist to your desktop, etc...? shocked

The defaults system has gotten very aggressive about caching. The phrases "move ~/Library/Preferences/whatever.plist to ..." and "delete/trash ~/Library/Preferences/whatever.plist" should set off alarms. They do not (reliably) do what you think they do, even though they used to (sort of).

The "defaults system" is embodied in a background process named cfprefsd (short for Core Foundation PREFerenceS Daemon"). Initially, right after login, cfprefsd knows nothing. As applications start up, they ask cfprefsd for their saved settings. The first time each application asks, cfprefsd reads and memorizes the corresponding .plist file. If an application changes a setting, it tells cfprefsd, which adjusts its memory of the application's settings. By and by, cfprefsd will write its amended knowledge to the .plist file, completely overwriting the previous file if it's still there.

The point is, cfprefsd tries to read the .plist file only once. Once it has read the file, nothing you do to the file has any effect on that application's defaults. (It used to be that when the application quit, cfprefsd would write out any changes and then forget the file. Relaunching the application would cause it to again ask cfprefsd for its settings, at which time cfprefsd would try re-reading the file. That opened up a window for you; deleting/moving the .plist file while the application was not running was an event that cfprefsd would notice. cfprefsd no longer forgets so quickly.)

The proper way to "forget" an application's saved preferences is to tell cfprefsd to delete them. cfprefsd will eventually propagate that deletion back to the .plist file, either by deleting it or rewriting it as an essentially empty file, but that's an implementation detail. The important point is that you should not be manipulating the .plist file yourself. Let cfprefsd manipulate the file.

Your interface to cfprefsd is through the defaults command in Terminal.

If you suspect an application's preferences have somehow gotten garbled, and want to set them back to their initial settings:
  • Quit the application. (Once an application has gotten a value from cfprefsd, it may itself cache the value, and nothing you tell cfprefsd will budge the application's memory of The Way Things Areâ„¢.)
  • Optionally, move the .plist file elsewhere. (You're only doing this so you can later restore these settings. This move does not affect cfprefsd.)
  • In Terminal, enter the command:
    defaults delete application.bundle.id
  • Re-launch the application.
If you've saved a previous .plist file and want to restore it:
  • Quit the application. (Same reason as before.)
  • In Terminal, enter the command:
    defaults write application.bundle.id "$(defaults read path/to/saved.plist)"
    This copies the saved file into cfprefsd's memory, making it available to the app and eventually causing the .plist file to be re-written.
  • Re-launch the app.


Each application has a "bundle id", which is how it identifies itself to cfprefsd when it asks for "its" saved settings, and is therefore how you must identify the app in the defaults command. Sometimes the bundle id is obvious (for example, Safari's is com.apple.Safari), but sometimes less so (for example, Calendar's is com.apple.iCal). You can learn an application's bundle id by entering the Terminal command
osascript -e 'id of application "application name" '

For example, try
osascript -e 'id of application "Contacts" '

Alternatively, the application's preferences are stored in ~/Library/Preferences/application.bundle.id.plist, so if you've found that file you can just pull the application.bundle.id from the filename.


What an amazing tutorial, ganbustein. I am both overwhelmed and appreciative. Me thinks a bit (a great big bit) of digesting will necessary before I comprehend what I know. My eyes are still glazed…

Before seeing your post, it dawned on me to use Shortcuts. And that works as divined. AFAIK, all is again right with the world.

Still, I eagerly (and perhaps foolishly) await 10.10.2 in hopes that will actually fix things, vice the work around I created.

Truly, ganbustein, your time & expertise are most valued, and I shall continue doing my homework.
First, I'll second Harv's appreciation of your tutorial (not to mention the many others you've posted). The depth of your knowledge of OS X has frequently left me wondering about its source.

As regards the deletion of plists, though, while I understand your point that "you should not be manipulating the .plist file yourself", OS X offers more than one seat-of-the-pants methods for accomplishing tasks that should, ideally, be carried out via Terminal, and this seems to be an instance thereof.

Quote:
The "defaults system" is embodied in a background process named cfprefsd (short for Core Foundation PREFerenceS Daemon"). Initially, right after login, cfprefsd knows nothing. As applications start up, they ask cfprefsd for their saved settings. (Emphasis added)

Since plist deletion instructions traditionally include either logging out/in or restarting with the expectation that a new, default plist will have been created, won't cfprefsd's loading said new, default plist at login achieve the precise results that were envisioned when the original plist was deleted?
Originally Posted By: artie505
Since plist deletion instructions traditionally include either logging out/in or restarting with the expectation that a new, default plist will have been created, won't cfprefsd's loading said new, default plist at login achieve the precise results that were envisioned when the original plist was deleted?

Still not reliable. If at the time you log out cfprefsd believes that it is holding updated information that has not yet been written to disk, it will re-write the .plist file at that time, creating it if necessary. The end result is exactly as if you had not deleted the file.

There was always a window of vulnerability for this to happen, so it was never guaranteed that deleting the .plist file would change anything. What's new is that the window is considerably larger than it used to be.

The only certain way to get an application's preferences deleted (that is, set back to factory defaults) is to tell cfprefsd to do it. The only way for a user to talk to cfprefsd is through the defaults command at the command line.

This is not a matter of having more than one way to do something, and choosing one method over another based on the situation or personal preferences. This is a matter of having one right way to do it, and one wrong way that may accidentally work some of the time. The "sometimes works" aspect may delude you into thinking it always works.

Notice also that resetting the preferences via defaults/cfprefsd happens immediately. There is no need to log out and back in, making this a much lighter-weight solution. (You do still have to quit/relaunch the app, because the app may have cached the answer it got from cfprefsd, and you need to force it to ask again.)
Got it! Thanks. smile
I'll also say I really despise defaults now being the required way to change a plist. It's essentially impossible to edit keyed sub-dictionaries with Defaults, (you have to send what often ends up being a huge tree of data, weirdly formatted, to outright replace the entire dictionary)

afaik, apple's "recommended" way to adjust arrays and dictionaries is to use plistbuddy, which is included in some apple stuff even, but it is specifically NOT compatible with that cfprefs daemon madness.

The end result then is, there's NO approved (or reliable for that matter) way to edit a plist's dictionaries and arrays as of right now. I have a complex script that constructs base images from scratch, and it makes extensive adjustments to plists. For things that require buddy, it kills the prefs daemon immediately after making changes, forcing it to recache them from disk, instead of overwriting them. Works most of the time. Editing settings in open apps (like Finder) is still unreliable.
Originally Posted By: Virtual1
The end result then is, there's NO approved (or reliable for that matter) way to edit a plist's dictionaries and arrays as of right now. I have a complex script that constructs base images from scratch, and it makes extensive adjustments to plists. For things that require buddy, it kills the prefs daemon immediately after making changes, forcing it to recache them from disk, instead of overwriting them. Works most of the time. Editing settings in open apps (like Finder) is still unreliable.

I strongly recommend against killing cfprefsd. That discards all unsaved settings for all apps. Avoid the shotgun approach; it can get the job done, but can also lead to massive collateral damage. In fact, I get twitchy anytime I see someone casually suggesting killall. (All??? You want to kill all of them? Surely there's only one in particular you need to kill. Killing all of them seems like possible overkill. Sort of like Terminator going through the phone book killing all the Sarah Conners, when he only needed to kill one. And you see where it got him. The pattern was noticed before he got to her and she was forewarned. Overkill has its consequences.)


It sounds like you're pre-populating defaults for a new user. One option is to edit the .plist files while the user is not logged in. (cfprefsd is a UserAgent: one copy per user running only when the user is logged in.) Either become root to access ~otheruser/Library/Preferences, or use su -l otheruser to create a Terminal session as that user without firing up that user's UserAgents. Of course, in the latter case the first use of defaults will fire it up anyway, but it should read only the files corresponding to preference domains you ask about.

Alternatively, you can build the .plist file exactly as you want, but in a different directory, and then send the whole thing to cfprefsd using

defaults write app.bundle.id "$(defaults read path/to/the.plist)"

Ignore the part of the man defaults page that says the new value must be enclosed in single quotes. What they mean is that the entire value must be passed in as a single argument, which could be done with single quotes around a literal string, but is more conveniently done here with double-quotes around a calculated string.

Yes, it means you're piping the entire file into cfprefsd, but on the other hand you were expecting cfprefsd to re-read the entire file. Efficiency-wise it's a wash. And, you can still use PlistBuddy to your heart's content. (PlistBuddy now seems to be part of a standard install, but it's in /usr/libexec instead of one of the directories on the standard path. Much better than the old days when you had to paw through ~/Library/Receipts looking for a copy.)

You don't need to replace the entire file. For example, Finder's ListViewSettings is a complex value, but you could construct a .plist file containing just just that value, and then install it with

defaults write com.apple.Finder ListViewSettings "$(defaults read path/to/ListViewSettings.plist)"

That only works one level down, of course.

The new file doesn't need to be in any particular .plist format. It could be a text file in the old-fashioned NextStep property list format (which, conveniently, is the format that defaults read produces). In that case, you can edit it with any text-editing app, including vim, bbedit, sed, awk, et al., and then import it with

defaults write app.bundle.id "$(cat path/to/plist.txt)"

Which actually opens up more options for you. Your workflow can be

defaults read app.bundle.id [topLevelStructure] > path/to/temp.txt
edit the temp.txt file using any convenient tools
defaults write app.bundle.id [topLevelStructure] "$(cat path/to/temp.txt)"

In short, I think that playing nicely with cfprefsd may force you to change your ways, but the new ways needn't be noticeably more difficult for you.
thanks for the breakdown gan, but unfortunately those approaches won't work for me here.

Yes I am running a script to set up a new user. the new user currently logged in actually. (this user will then be exported to the new user template) Nothing else is being set by any other app, the script is expected do as much of the setup as physically possible, including installing software and verifying software is present and version numbers are correct. So killing the daemon harms nothing.

Building the plist isn't an option, there are somewhere around 100 things getting changed in the plists. (and at least half that many things being set by other means like dsconfigad) I'm not going to edit 100 plists by hand. That approach would get much uglier if I wanted to make several different changes in the same plist. it would be too easy to overwrite a change by trying to add another later.

Sending entire trees into defaults is a nightmare. it becomes a nightmare within a nightmare when you are dealing with nested trees, such as changing default search paths on all the network adapters. NOT going there. Not more than once anyway. I have surrendered to that technique in exactly one place due to lack of options. Such changes are very difficult to verify, and my script vigorously verifies things, and only changes what needs to be changed. It can be ran over and over, and often needs to be run several times as I address all the things its pointing out I need to do (installs and updates mostly) which I will do a few at a time.

I spent several days looking for ways to "play nicely" with cfprefsd, but the bottom line was it doesn't want to play nice. Two Apple engineers backed me up on this opinion.

I don't see the problem.

No matter how many changes you're making, you're making them one at a time. Any change that does not involve editing a plist file is already playing nicely with cfprefsd. For any change that does involve editing a plist, ask cfprefsd to give you your own copy of the file, edit that, then hand it back to cfprefsd, and again you're playing nicely.

You don't need to do any manual edits that you aren't doing already. Automated edits can work just as easily against a copy of the plist as against the original.

What do you care if entire trees are being tossed around? You don't need to see them; only your scripts do. It's no more work for cfprefsd to handle an entire tree you give it than to re-read an entire plist file. It's not like cfprefsd ever reads only part of a file.

For that matter, any edit involves passing around an entire tree. Do you think PlistBuddy doesn't read the entire input file and write the entire output file? Or sed? Or awk? Whatever tool your scripts are using to edit your plist files slurps up the entire file, applies edits internally, and spits out the entire updated file.

I just don't see the problem.
© FineTunedMac