Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always store UTIs for include/exclude types in FieSystemObjectSources (supersedes #1681) #1708

Merged
merged 13 commits into from Jan 17, 2014

Conversation

pjrobertson
Copy link
Member

@pjrobertson pjrobertson commented Dec 6, 2013

See #1681 for more of the discussion

Instead of fiddling with UTIs in the QSDirectoryScanner, I think it's much more wise to just always store the UTI for the include/exclude types option (be it dyn-xxx or not)
This has some fancy benefits of being able to show the nice name for OSTypes (e.g. if you enter 'fold' you'll see folder in the token, instead of 'fold' like it used to be, and also you can see the UTI from the popup of the menu item (just like I've done for the bundle ID for trigger scope)

@skurfer
Copy link
Member

@skurfer skurfer commented Dec 6, 2013

OK, I’ll give this a try. What would happen if you store the dyn- UTI for an unknown type, then later install some application that gives it a nicer UTI? (If I could think of a way to test that, I would. I wonder if removing TextMate would cause Markdown to go unrecognized.)

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Dec 6, 2013

Dunno, I’d let the OS handle that - hopefully it’s clever enough

You could test it:

  • set an excludes type as “.sillyextension”
  • Edit Quicksilver’s Info.plist to add an entry for “sillyextension” The format is all there for qspkg and qsplugin already

On 6 Rhag 2013, at 12:05, Rob McBroom notifications@github.com wrote:

OK, I’ll give this a try. What would happen if you store the dyn- UTI for an unknown type, then later install some application that gives it a nicer UTI? (If I could think of a way to test that, I would. I wonder if removing TextMate would cause Markdown to go unrecognized.)


Reply to this email directly or view it on GitHub.

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Dec 6, 2013

and… drum roll… storing a dyn- UTI and later checking it for conformance with a real UTI doesn’t work. See the latest few commits for a fix for that - I had to create a better UTTypeConformsTo function ;-)

Good spot/idea

On 6 Rhag 2013, at 12:16, Patrick Robertson robertson.patrick@gmail.com wrote:

Dunno, I’d let the OS handle that - hopefully it’s clever enough

You could test it:

  • set an excludes type as “.sillyextension”
  • Edit Quicksilver’s Info.plist to add an entry for “sillyextension” The format is all there for qspkg and qsplugin already

On 6 Rhag 2013, at 12:05, Rob McBroom notifications@github.com wrote:

OK, I’ll give this a try. What would happen if you store the dyn- UTI for an unknown type, then later install some application that gives it a nicer UTI? (If I could think of a way to test that, I would. I wonder if removing TextMate would cause Markdown to go unrecognized.)


Reply to this email directly or view it on GitHub.

@tiennou
Copy link
Member

@tiennou tiennou commented Dec 6, 2013

Well, I don't like QSIsUTI ;-). What happens when Apple stops using dots in dynamic UTIs ? What happen if you pass it a non-file (eg. "public.item") UTI ? (that's rhetoric btw ;-)).

I also think you could make it an internal (eg. static) function and check parameters with it (so 86a2af4, d8f2690 just disappear).

I'm also surprised by the conforming check failing, because that's the whole point of UTI. So either the OS bugs out (and your workaround is fine), or we're generating the UTI wrong in the first place... I'm currently working again on my UTI unpacker — as soon as I have that ready, we'll be able to understand what dyn UTIs actually mean.

EDIT: Have you checked that LaunchServices registered the new UTI ? (search lsregister)

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Dec 6, 2013

I'm also surprised by the conforming check failing, because that's the whole point of UTI. So either the OS bugs out (and your workaround is fine), or we're generating the UTI wrong in the first place... I'm currently working again on my UTI unpacker — as soon as I have that ready, we'll be able to understand what dyn UTIs actually mean.

Yep, me too. You’ll see from my previous comment that I said “The OS should take care of that - that’s the whole point of UTIs"… but it doesn’t
One possible explanation (I previously mentioned). The UTType… functions return different UTIs to the one retrieved from the resource of an NSURL

What happens when Apple stops using dots in dynamic UTIs ? What happen if you pass it a non-file (eg. "public.item") UTI ? (that's rhetoric btw ;-)).

Yes, it’s fragile, but for now it’s the best we’ve got. How would you determine if something’s a UTI? :/
Stupidly, Apple didn’t add a “one UTI to rule them all”. e.g. public.toilet - for which every other UTI in the universe should conform to (sorry, I just had to - I was originally going to use public.thing)

On 6 Rhag 2013, at 19:24, Etienne Samson notifications@github.com wrote:

Well, I don't like QSIsUTI ;-). What happens when Apple stops using dots in dynamic UTIs ? What happen if you pass it a non-file (eg. "public.item") UTI ? (that's rhetoric btw ;-)).

I also think you could make it an internal (eg. static) function and check parameters with it (so 86a2af4, d8f2690 just disappear).

I'm also surprised by the conforming check failing, because that's the whole point of UTI. So either the OS bugs out (and your workaround is fine), or we're generating the UTI wrong in the first place... I'm currently working again on my UTI unpacker — as soon as I have that ready, we'll be able to understand what dyn UTIs actually mean.


Reply to this email directly or view it on GitHub.

@tiennou
Copy link
Member

@tiennou tiennou commented Dec 6, 2013

How would you determine if something’s a UTI? :/
As per the UTI Prog Guide, there should only be 2 "root" UTIs : public.content (for plain old bytes) and public.item (for filesystem objects).

I'm just wary of what others application will declare as UTIs — suppose the guy who exports "sillyextension" doesn't use the recommended reverse DNS notation. If you want some cold hard proofs, you should get a look at the output of lsregister (both insightful and depressing).

Stupidly, Apple didn’t add a “one UTI to rule them all”.

I'm pretty sure there's a good reason ;-). UTIs are tree-based, and maybe having one single tree would have imposed too much burden when doing lookups or something else (like, it wouldn't account for the case when someone wants it's own root UTI, like, "qs.object", if you see where I'm heading ;-)).

One possible explanation (I previously mentioned). The UTType… functions return different UTIs to the one retrieved from the resource of an NSURL

I'm also dubious on that one (not about your work, but as the saying more-or-less goes, "If there's a bug in the OS, it's likely in your application" ;-)). I plan on juggling that UTI problem, but I was just wondering if the behavior changes if you pass a "conformingTo" UTI to UTTypeCreatePreferredIdentifierForTag?

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Dec 6, 2013

Off out, but I thought I’d do this quickly before I left. Maybe it needs some work, but you get the point ;-)

http://d.pr/f/UUoW

On 6 Rhag 2013, at 20:07, Etienne Samson notifications@github.com wrote:

How would you determine if something’s a UTI? :/
As per the UTI Prog Guide, there should only be 2 "root" UTIs : public.content (for plain old bytes) and public.item (for filesystem objects).

I'm just wary of what others application will declare as UTIs — suppose the guy who exports "sillyextension" doesn't use the recommended reverse DNS notation. If you want some cold hard proofs, you should get a look at the output of lsregister (both insightful and depressing).

Stupidly, Apple didn’t add a “one UTI to rule them all”.

I'm pretty sure there's a good reason ;-). UTIs are tree-based, and maybe having one single tree would have imposed too much burden when doing lookups or something else (like, it wouldn't account for the case when someone wants it's own root UTI, like, "qs.object", if you see where I'm heading ;-)).

One possible explanation (I previously mentioned). The UTType… functions return different UTIs to the one retrieved from the resource of an NSURL

I'm also dubious on that one (not about your work, but as the saying more-or-less goes, "If there's a bug in the OS, it's likely in your application" ;-)). I plan on juggling that UTI problem, but I was just wondering if the behavior changes if you pass a "conformingTo" UTI to UTTypeCreatePreferredIdentifierForTag?


Reply to this email directly or view it on GitHub.

@tiennou
Copy link
Member

@tiennou tiennou commented Dec 6, 2013

Ok, now my eyes are open, and this is a mess... Here's your modified project :

https://www.dropbox.com/s/vkbozkfp2jec1rb/UTITest%202.zip

  • I've dropped the LSInfoRec part because we can't do anything more with it : we already have the extension, and the OSType is always NULL because sillyextension isn't registered.
  • Whatever you pass as the conformingUTI, the conformance test never works. Now I really need to crack open those dyn things, because I don't get how this can fail...
  • I got a nil response from NSURL the first time I ran the program (I've added error reporting ftm), but it never happened again.
  • I've also checked the "AllIdentifier" versions : they just return an array, which contains the same dyn UTIs.
  • I'm suspecting my LS database now, so I'll (sadly) have to try to kill it and reseed it... Doesn't change anything.
  • I've added tests for the NSWorkspace methods. Seems to work the same as UTTypeConformsTo/UTCreatePreferedIdentifierForTag.
  • I've added the needed registration info for "sillyextension" in that test app's plist. Everyone saw it except NSURL, which still returns the old dyn UTI. But the conforming test for it returns YES. What the...

EDITED

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Dec 6, 2013

Hehe, I’m glad I’ve given you something fun to play with* :P

  • I've dropped the LSInfoRec part because we can't do anything more with it : we already have the extension, and the OSType is always NULL because sillyextension isn't registered.

FYI that’s what we’re currently using in Quicksilver. I wanted to move to using just the NSURL method, but of course that only works for files

  • Disclaimer: I may cause side effects such as headaches. Sorry :(

On 6 Rhag 2013, at 21:48, Etienne Samson notifications@github.com wrote:

Ok, now my eyes are open, and this is a mess... Here's your modified project :

https://www.dropbox.com/s/vkbozkfp2jec1rb/UTITest%202.zip

I've dropped the LSInfoRec part because we can't do anything more with it : we already have the extension, and the OSType is always NULL because sillyextension isn't registered.
Whatever you pass as the conformingUTI, the test never works. Now I really need to crack open those dyn things, because I don't get how this can fail...
I got a nil response from NSURL the first time I ran the program (I've added error reporting ftm), but it never happened again.
I've also checked the "AllIdentifier" versions : they just return an array, which contains the same dyn UTIs.
I'm suspecting my LS database now, so I'll (sadly) have to try to kill it and reseed it...

Reply to this email directly or view it on GitHub.

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Dec 6, 2013

P.S. I think we should register is.patrick.sillyfile globally :)

On 6 Rhag 2013, at 23:49, Patrick Robertson robertson.patrick@gmail.com wrote:

Hehe, I’m glad I’ve given you something fun to play with* :P

• I've dropped the LSInfoRec part because we can't do anything more with it : we already have the extension, and the OSType is always NULL because sillyextension isn't registered.

FYI that’s what we’re currently using in Quicksilver. I wanted to move to using just the NSURL method, but of course that only works for files

  • Disclaimer: I may cause side effects such as headaches. Sorry :(

On 6 Rhag 2013, at 21:48, Etienne Samson notifications@github.com wrote:

Ok, now my eyes are open, and this is a mess... Here's your modified project :

https://www.dropbox.com/s/vkbozkfp2jec1rb/UTITest%202.zip

I've dropped the LSInfoRec part because we can't do anything more with it : we already have the extension, and the OSType is always NULL because sillyextension isn't registered.
Whatever you pass as the conformingUTI, the test never works. Now I really need to crack open those dyn things, because I don't get how this can fail...
I got a nil response from NSURL the first time I ran the program (I've added error reporting ftm), but it never happened again.
I've also checked the "AllIdentifier" versions : they just return an array, which contains the same dyn UTIs.
I'm suspecting my LS database now, so I'll (sadly) have to try to kill it and reseed it...

Reply to this email directly or view it on GitHub.

@tiennou
Copy link
Member

@tiennou tiennou commented Dec 6, 2013

FYI that’s what we’re currently using in Quicksilver.

Yep, just to get the OSType (which are being phased out) or the file's extension (which we can get by other means). I'm not sure of the performance implications though...

I wanted to move to using just the NSURL method, but of course that only works for files.

Which is the majority of the use cases as of now (there's no API in Cocoa that works like file(1) but returns an UTI, e.g. -[NSData dataUTI] — would be awesome though — unless you're messing with pasteboards).

Given the few gotchas above, I'm not sure it's reliable enough. I haven't been able to reproduce the nil bug, but the "caching one" isn't nice anyway (though given the "conforming" tests results, that's not as cumbersome). I'd prefer to stick to the NSWorkspace method, since it gives consistent results.

P.S. I think we should register is.patrick.sillyfile globally :)

Yeah, I used the bundle ID, but the name sound cool ;-).

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Jan 14, 2014

OK @tiennou, this post may be of interest to you: http://webcache.googleusercontent.com/search?q=cache:zHQtElQ9KlAJ:alastairs-place.net/blog/2012/06/06/utis-are-better-than-you-think-and-heres-why+&cd=5&hl=en&ct=clnk&gl=uk (seems like the actual page isn't loading right now)

The reason the generated dyn.x... UTI is different depending on how we generate it is because the stored information is different. The short one specifies only the file extension, the longer one also a MIME type and perhaps a conformsTo value. So all in all, I think it works fine.

I still think this is perfectly fine to be merged (Except for the conflict now of course) - are people still not happy with the QSIsUTI() function (@tiennou?) I will work on another solution now, and see what you think

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Jan 14, 2014

OK, I'm 100% happy with my QSIsUTI method (after a little bit of tweaking...)

If people are stupid enough to define their own custom UTI that doesn't use the reverse DNS/dot syntax then their apps will not work. Apple seems to laugh at these people.

Using the UTITest app above, I did the following:

  • Cleared my launch services database
  • Edited the info.plist to give the Silly File file an Identifier of nodotsilly
  • Ran the app: All the generated UTIs from the various methods started with dyn. and none conformed to public.item
  • Re-cleared my launch services database
  • Edited the info.plist to give the Silly File an identifier of com.qsapp.niceuti
  • Ran the app: The NSURL UTI was prefixed dyn., all others gave com.qsapp.niceuti. All methods showed conformance with public.item.

So this goes to show that UTIs won't work if they don't use the reverse DNS, so we don't need to worry about that use case :)

@tiennou
Copy link
Member

@tiennou tiennou commented Jan 14, 2014

Yeah, I pointed that post in IRC a few months ago (I'm still trying to write an UTI unpacker because of that, but I'm stuck at the "custom" base32 decoding part).

You're right, they're different because they contain different stuff. I'm still a little unsure about the "works fine" part though, but I'm too time-constrained atm so I'll keep my "not-happyiness" for the being ;-).

Also, since I started to comment, I found out about the nil bug I encountered above : I have Hazel setup to automatically move stuff on the Desktop to a subfolder (so it's always clean). That was a race between creating the file, Hazel stashing it away and NSWorkspace not finding it afterwards.

@pjrobertson
Copy link
Member Author

@pjrobertson pjrobertson commented Jan 15, 2014

OK to test

pjrobertson added 3 commits Jan 15, 2014
For some UTIs (like com.apple.xcode.project) the description of the UTI is 'content'. Not very helpful
file extensions on folders can be misleading. Fixes #1742
// Try to get the UTI from the extension/string
if ([editingString hasPrefix:@"'"]) {
// 'xxxx' strings are OS types
NSString *OSTypeAsString = [editingString stringByReplacingOccurrencesOfString:@"'" withString:@""];
Copy link
Member

@skurfer skurfer Jan 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be using stringByTrimmingCharactersInSet:, too. Then, I think this can be merged.

Copy link
Member Author

@pjrobertson pjrobertson Jan 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK done. If/when I implement a QSUTIManager singleton class this'll be something else it'll do. I've made a note of it in a comment, you'll see

skurfer added a commit that referenced this issue Jan 17, 2014
Always store UTIs for include/exclude types in FieSystemObjectSources (supersedes #1681)
@skurfer skurfer merged commit d9a500d into master Jan 17, 2014
1 check passed
@skurfer skurfer deleted the i1681 branch Jan 17, 2014
skurfer added a commit that referenced this issue Jan 17, 2014
skurfer added a commit that referenced this issue Jan 17, 2014
skurfer
Copy link
Member

@skurfer skurfer commented on d6391b0 Jan 20, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, unfortunately this breaks the System Preferences scanner and one of my custom entries that only includes com.apple.xcode.project. Looking into it.

skurfer added a commit that referenced this issue Jan 21, 2014
skurfer added a commit that referenced this issue Jan 25, 2014
skurfer added a commit that referenced this issue Feb 2, 2014
skurfer added a commit that referenced this issue Feb 2, 2014
skurfer added a commit that referenced this issue Feb 5, 2014
skurfer added a commit that referenced this issue Feb 11, 2014
skurfer added a commit that referenced this issue Mar 19, 2014
skurfer added a commit that referenced this issue Apr 14, 2014
skurfer added a commit that referenced this issue May 13, 2014
skurfer added a commit that referenced this issue May 30, 2014
skurfer added a commit that referenced this issue Aug 7, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants